// Copyright (c) 2009 Christopher Keith (chris.keith@gmail.com)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

// Demonstrate simple command lookup in Java.
// See usage() method below for instructions.

import java.io.*;
import java.lang.reflect.*;
import java.util.*;

class Dscl {
	private	boolean mDebug = false;

	private void usage() {
		String msgs[] = {
			"This program demonstrates simple command lookups.",
			"For example: \"C:\\Program Files\\Java\\jdk1.6.0_03\\bin\\javac\" Dscl.java",
			"(or \"/cygdrive/c/Program Files/Java/jdk1.6.0_03/bin/javac\" Dscl.java",
			"then: java Dscl < testdata.txt"
		};
		for (String s : msgs) {
			System.out.println(s);
		}
	}
	private void exit(String s) {
		usage();
		System.out.println(s);
		System.exit(1);
	}
	public void reverse(String[] params) {
		String s = "";
		for (String p : params) {
			s = p + " " + s;
		}
		System.out.println(s);
	}
	public void doprint(String[] params) {
		for (String s : params) {
			System.out.print(s + " ");
		}
		System.out.println("");
	}
	public void debug(String[] params) {
		mDebug = true;
	}
	private void printMethods() {
		Method methlist[] = getClass().getDeclaredMethods();
		for (int i = 0; i < methlist.length; i++) {  
			Method m = methlist[i];
			System.out.println("name = " + m.getName());
			System.out.println("decl class = " + m.getDeclaringClass());
			Class<?> pvec[] = m.getParameterTypes();
			for (int j = 0; j < pvec.length; j++)
				System.out.println(" param #" + j + " " + pvec[j]);
			Class<?> evec[] = m.getExceptionTypes();
			for (int j = 0; j < evec.length; j++)
				System.out.println("exc #" + j + " " + evec[j]);
			System.out.println("return type = " + m.getReturnType());
			System.out.println("-----");
		}
	}
	private void handleCommand(String s) {
		if (s.length() > 2) {
			String[] tokens = s.split(s.substring(0,1));
			if (mDebug) {
				doprint(tokens);
			}
			if (tokens.length > 1) {
				try {
					Class<?> partypes[] = new Class[1];
					partypes[0] = String[].class;
					Method meth = getClass().getMethod(tokens[1], partypes);
					if (meth == null) {
						printMethods();
						doprint(tokens);
						exit("Unknown command.");
					}
					Object arglist[] = new Object[1];
					String[] subArray = new String[tokens.length - 2];
					System.arraycopy(tokens, 2, subArray, 0, tokens.length - 2);

					arglist[0] = subArray;
					meth.invoke(this, arglist);
				} catch (Exception e) {
					printMethods();
					e.printStackTrace();
					doprint(tokens);
					exit("Exception caught.");
				}
			}
		}
	}
	public void doIt(String[] args) {
		try {
			BufferedReader fh = new BufferedReader(new InputStreamReader(System.in), 32767);
			String	f1;
			while ((f1 = fh.readLine()) != null) {
				handleCommand(f1);
			}
			fh.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		Dscl	d = new Dscl();
		d.doIt(args);
	}
}
